package com.huangfu.learning.javabase.java.pattern.action.mediator;

/**
 * Created with IntelliJ IDEA.
 * Author: huangfu.daohui
 * Date: 2018/8/16
 * Time: 18:55
 * Version: 1.0
 * Description:中介者模式：用来降低多个对象和类之间的通信复杂性。这种模式提供了一个中介类，该类通常处理不同类之间的通信，并支持松耦合，使代码易于维护
 * 参考：https://blog.csdn.net/itachi85/article/details/60466829
 * https://www.cnblogs.com/snaildev/p/7686908.html
 * 4个角色：
 * 1、Mediator：抽象中介者角色，定义了同事对象到中介者对象的接口，一般以抽象类的方式实现。
 * 2、ConcreteMediator：具体中介者角色，继承于抽象中介者，实现了父类定义的方法，它从具体的同事对象接受消息，向具体同事对象发出命令。
 * 3、Colleague：抽象同事类角色，定义了中介者对象的接口，它只知道中介者而不知道其他的同事对象。
 * 4、ConcreteColleague1、ConcreteColleague2：具体同事类角色，继承于抽象同事类，每个具体同事类都知道本身在小范围的行为，而不知道在大范围内的目的
 * <p>
 * 应用实例： 1、中国加入 WTO 之前是各个国家相互贸易，结构复杂，现在是各个国家通过 WTO 来互相贸易。 2、机场调度系统。 3、MVC 框架，其中C（控制器）就是 M（模型）和 V（视图）的中介者。
 * <p>
 * 优点： 1、降低了类的复杂度，将一对多转化成了一对一。 2、各个类之间的解耦。 3、符合迪米特原则。
 * 缺点：中介者会庞大，变得复杂难以维护
 * <p>
 * 主要解决：对象与对象之间存在大量的关联关系，这样势必会导致系统的结构变得很复杂，同时若一个对象发生改变，我们也需要跟踪与之相关联的对象，同时做出相应的处理。
 * 实例：
 * 中介者模式可以拿武侠来举例，江湖中门派众多，门派之前因为想法不同会有很多的利益冲突，这样就会带来无休止的纷争。为了江湖的安宁，大家推举出了一个大家都认可的武林盟主来对江湖纷争进行调停。
 * 前段时间武当派和峨眉派的的弟子被大力金刚指所杀，大力金刚指是少林派的绝学，因为事情重大，而且少林派实力强大，武当派和峨眉派不能够直接去少林派去问罪，只能上报武林盟主由武林盟主出面进行调停，
 */
public class MediatorPattern {

    public static void main(String[] args) {
        Champions champions = new Champions();
        Wudang wudang = new Wudang(champions);
        Shaolin shaolin = new Shaolin(champions);
        Emei emei = new Emei(champions);
        champions.setWudang(wudang);
        champions.setShaolin(shaolin);
        champions.setEmei(emei);
        wudang.sendAlliance("武当弟子被少林大力金刚指所杀");
        emei.sendAlliance("峨眉弟子被少林大力金刚指所杀");
        shaolin.sendAlliance("少林弟子绝不会做出这种事情");
    }
}

//首先我们创建抽象中介者类，在这个例子中，它是一个武林联盟类，如下所示。
abstract class WulinAlliance {
    //United为抽象同事类也就是门派类，接下来我们来创建它
    abstract void notice(String message, United united);
}

//United为抽象同事类也就是门派类，接下来我们来创建它
class United {
    protected WulinAlliance wulinAlliance;

    public United(WulinAlliance wulinAlliance) {
        this.wulinAlliance = wulinAlliance;
    }
}

/**
 * 武当、峨眉和少林类都有两个方法，其中getNotice方法是自有方法，对于其他的门派（同事类）和武林联盟（中介者）没有依赖，
 * 只是用来接收武林盟主的通知。sendAlliance方法则是依赖方法，它必须通过武林盟主才能完成行为。
 * 具体同事类（武当）
 */
class Wudang extends United {

    public Wudang(WulinAlliance wulinAlliance) {
        super(wulinAlliance);
    }

    // 去武林盟主哪里告状
    void sendAlliance(String message) {
        wulinAlliance.notice(message, this);
    }

    //收到消息
    void getMessage(String message) {
        System.out.println("武当收到消息：" + message);
    }
}

/**
 * 具体同事类（峨眉）
 */
class Emei extends United {

    public Emei(WulinAlliance wulinAlliance) {
        super(wulinAlliance);
    }

    // 去武林盟主哪里告状
    void sendAlliance(String message) {
        wulinAlliance.notice(message, this);
    }

    //收到消息
    void getMessage(String message) {
        System.out.println("峨眉收到消息：" + message);
    }
}

/**
 * 具体同事类（少林）
 */
class Shaolin extends United {

    public Shaolin(WulinAlliance wulinAlliance) {
        super(wulinAlliance);
    }

    // 去武林盟主哪里告状
    void sendAlliance(String message) {
        wulinAlliance.notice(message, this);
    }

    //收到消息
    void getMessage(String message) {
        System.out.println("少林收到消息：" + message);
    }
}

//具体中介者类则是武林盟主
class Champions extends WulinAlliance {

    private Wudang wudang;
    private Shaolin shaolin;
    private Emei emei;

    public void setWudang(Wudang wudang) {
        this.wudang = wudang;
    }

    public void setEmei(Emei emei) {
        this.emei = emei;
    }

    public void setShaolin(Shaolin shaolin) {
        this.shaolin = shaolin;
    }

    @Override
    public void notice(String message, United united) {
        if (united == wudang) {
            shaolin.getMessage(message);
        } else if (united == emei) {
            shaolin.getMessage(message);
        } else if (united == shaolin) {
            wudang.getMessage(message);
            emei.getMessage(message);
        }
    }
}